﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Aspose.GmailSync.Data;
using Aspose.GmailSync.Components;
using Aspose.Email.Mail;
using Aspose.Email.Google;
using Aspose.Email.Services.Google;
using System.Web.Security;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Persistence;
using Umbraco.Core;
using Umbraco.Web;
using Umbraco.Core.Models.Membership;
using System.Linq;

namespace Aspose.GmailSync
{
    public partial class GmailSync : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        private bool GmailSettingsExist
        {
            get
            {
                Aspose_GmailSync_ServerDetails gmailDetailsList = DatabaseHelper.CheckGmailDetails(UmbracoAPIHelper.CurrentUserId);
                if (gmailDetailsList != null)
                {
                    ViewState["GmailDetails"] = gmailDetailsList;
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        private void ResetControls()
        {
            GmailToUmbracoSync.Visible = false;
            UmbracoToGmailSync.Visible = false;
            GmailSettings.Visible = false;
        }

        protected void GmailToUmbracoHyperLink_Click(object sender, EventArgs e)
        {
            ResetControls();

            if (GmailSettingsExist)
            {
                GmailToUmbracoSyncResetControls();
                GmailToUmbracoSync.Visible = true;
            }
            else
            {
                GmailSettings.Visible = true;
                GmailToUmbracoClickedHiddenField.Value = "true";
            }
        }

        protected void UmbracoToGmailHyperLink_Click(object sender, EventArgs e)
        {
            ResetControls();

            if (GmailSettingsExist)
            {
                UmbracoToGmailSyncResetControls();
                UmbracoToGmailSync.Visible = true;
            }
            else
            {
                GmailSettings.Visible = true;
                UmbracoToGmailClickedHiddenField.Value = "true";
            }
        }

        protected void GmailSettingsHyperLink_Click(object sender, EventArgs e)
        {
            Aspose_GmailSync_ServerDetails gmailDetailsList = DatabaseHelper.CheckGmailDetails(UmbracoAPIHelper.CurrentUserId);
            if (gmailDetailsList != null)
            {
                EmailAddressTextBox.Text = gmailDetailsList.Email;
                ClientIDTextBox.Text = gmailDetailsList.ClientID;
                PasswordTextBox.Text = gmailDetailsList.Password;
                ClientSecretTextBox.Text = gmailDetailsList.ClientSecret.ToString();
            }

            ResetControls();
            GmailSettings.Visible = true;
        }

        protected void SaveButton_Click(object sender, EventArgs e)
        {
            GmailCredsErrorDiv.Visible = false;

            Aspose_GmailSync_ServerDetails serverDetails = new Aspose_GmailSync_ServerDetails();

            serverDetails.Email = EmailAddressTextBox.Text.Trim();

            if (serverDetails.Email.Contains("@"))
            {
                serverDetails.Username = serverDetails.Email.Split('@')[0];
            }

            serverDetails.Password = PasswordTextBox.Text.Trim();
            serverDetails.ClientID = ClientIDTextBox.Text.Trim();
            serverDetails.ClientSecret = ClientSecretTextBox.Text.Trim();
            serverDetails.UserID = UmbracoAPIHelper.CurrentUserId;

            try
            {
                string refresh_token = string.Empty;

                //Code segment - START
                //This segment of code is used to get the refresh_token. In general, you do not have to refresh refresh_token every time, you need to do it once, and then use it to retrieve access-token.
                //Thus, use it once to retrieve the refresh_token and then use the refresh_token value each time.
                string access_token; string token_type; int expires_in;
                GoogleTestUser user = new GoogleTestUser(serverDetails.Username, serverDetails.Email, serverDetails.Password, serverDetails.ClientID, serverDetails.ClientSecret);
                GoogleOAuthHelper.GetAccessToken(user, out access_token, out refresh_token, out token_type, out expires_in);
                serverDetails.RefreshToken = refresh_token;
                //Code segment - END

                using (IGmailClient client = Aspose.Email.Google.GmailClient.GetInstance(serverDetails.ClientID, serverDetails.ClientSecret, serverDetails.RefreshToken))
                {
                    FeedEntryCollection groups = client.FetchAllGroups();
                }

            }
            catch (Exception)
            {
                GmailCredsErrorDiv.Visible = true;
                return;
            }

            serverDetails.Password = Crypto.Encrypt(serverDetails.Password);
            serverDetails.ClientID = Crypto.Encrypt(serverDetails.ClientID);
            serverDetails.ClientSecret = Crypto.Encrypt(serverDetails.ClientSecret);
            serverDetails.RefreshToken = Crypto.Encrypt(serverDetails.RefreshToken);

            DatabaseHelper.AddUpdateServerDetails(serverDetails);

            ResetControls();

            if (GmailToUmbracoClickedHiddenField.Value.Equals("true"))
            {
                GmailToUmbracoSync.Visible = true;
                GmailToUmbracoClickedHiddenField.Value = "false";
            }
            else if (UmbracoToGmailClickedHiddenField.Value.Equals("true"))
            {
                UmbracoToGmailSync.Visible = true;
                UmbracoToGmailClickedHiddenField.Value = "false";
            }
        }

        protected void CancelButton_Click(object sender, EventArgs e)
        {
            ResetControls();
        }

        #region Gmail To Umbraco

        public void GmailToUmbracoSyncResetControls()
        {
            ProcessSummaryDiv.Visible = GmailToUmbraco_MainDiv.Visible = NoRowSelectedErrorDiv.Visible = false;
            Into_Div.Visible = true;
        }

        protected void GmailToUmbracoSyncButton_Click(object sender, EventArgs e)
        {
            NoRowSelectedErrorDiv.Visible = false;

            if (ViewState["GmailDetails"] != null)
            {
                List<string> alreadyExistingList = new System.Collections.Generic.List<string>();

                List<string> contactsList = new List<string>();

                foreach (GridViewRow row in GmailContactsGridView.Rows)
                {
                    if (row.RowType == DataControlRowType.DataRow)
                    {
                        CheckBox chkRow = (row.Cells[0].FindControl("SelectedCheckBox") as CheckBox);
                        if (chkRow.Checked)
                        {
                            string email = GmailContactsGridView.DataKeys[row.RowIndex].Value.ToString();
                            contactsList.Add(email);
                        }
                    }
                }

                if (contactsList.Count > 0)
                {
                    Aspose_GmailSync_ServerDetails serverDetails = (Aspose_GmailSync_ServerDetails)ViewState["GmailDetails"];
                    List<Components.GmailContact> gmailContactsList = new List<Components.GmailContact>();

                    using (IGmailClient client = Aspose.Email.Google.GmailClient.GetInstance(serverDetails.ClientID, serverDetails.ClientSecret, serverDetails.RefreshToken))
                    {
                        Contact[] contacts = client.GetAllContacts();

                        if (UserRadioButton.Checked)
                        {
                            foreach (Contact contact in contacts)
                            {
                                if (contactsList.Contains(contact.EmailAddresses[0].Address))
                                {
                                    IUser user = ApplicationContext.Current.Services.UserService.GetByEmail(contact.EmailAddresses[0].Address);

                                    if (user == null)
                                        CreateUmbracoUser(contact);
                                    else
                                        alreadyExistingList.Add(contact.EmailAddresses[0].Address);
                                }
                            }
                        }
                        else
                        {
                            foreach (Contact contact in contacts)
                            {
                                if (contactsList.Contains(contact.EmailAddresses[0].Address))
                                {
                                    IMember member = ApplicationContext.Current.Services.MemberService.GetByEmail(contact.EmailAddresses[0].Address);
                                    if (member == null)
                                        CreateUmbracoMember(contact);
                                    else
                                        alreadyExistingList.Add(contact.EmailAddresses[0].Address);
                                }
                            }
                        }
                    }
                }
                else
                {
                    NoRowSelectedErrorDiv.Visible = true;
                    return;
                }

                ImportedLiteral.Text = string.Format("{0} contact(s) have been imported to Umbraco successfully.", (contactsList.Count - alreadyExistingList.Count));

                if (alreadyExistingList.Count > 0)
                {
                    AlreadyExistingLiteral.Text = "The following contacts already exists in Umbraco and therefore not imported";
                    foreach (string email in alreadyExistingList)
                        AlreadyExistingLiteral.Text += "<br>" + email;
                }

                ProcessSummaryDiv.Visible = true;
                Into_Div.Visible = false;
                GmailToUmbraco_MainDiv.Visible = false;
            }
        }

        private void CreateUmbracoUser(Contact contact)
        {
            var userService = ApplicationContext.Current.Services.UserService;
            var userType = userService.GetUserTypeByAlias(UserTypesDropDownList.SelectedValue);
            userService.CreateUserWithIdentity(contact.EmailAddresses[0].Address, contact.EmailAddresses[0].Address, userType);
        }

        private void CreateUmbracoMember(Contact contact)
        {
            var memberService = ApplicationContext.Current.Services.MemberService;
            var member = memberService.CreateMemberWithIdentity(contact.EmailAddresses[0].Address, contact.EmailAddresses[0].Address, contact.DisplayName, MemberTypesDropDownList.SelectedItem.Text);
        }

        private void RenderUserTypes()
        {
            var userService = ApplicationContext.Current.Services.UserService;
            UserTypesDropDownList.DataSource = userService.GetAllUserTypes();
            UserTypesDropDownList.DataBind();
        }

        private void RenderMemberTypes()
        {
            umbraco.cms.businesslogic.member.MemberType[] MemberTypes = umbraco.cms.businesslogic.member.MemberType.GetAll;
            MemberTypesDropDownList.DataSource = MemberTypes;
            MemberTypesDropDownList.DataBind();
        }

        protected void GetGmailContactsButton_Click(object sender, EventArgs e)
        {
            Into_Div.Visible = false;
            GmailToUmbraco_MainDiv.Visible = true;

            RenderUserTypes();
            RenderMemberTypes();

            if (ViewState["GmailDetails"] != null)
            {
                Aspose_GmailSync_ServerDetails serverDetails = (Aspose_GmailSync_ServerDetails)ViewState["GmailDetails"];
                List<Components.GmailContact> gmailContactsList = new List<Components.GmailContact>();

                using (IGmailClient client = Aspose.Email.Google.GmailClient.GetInstance(serverDetails.ClientID, serverDetails.ClientSecret, serverDetails.RefreshToken))
                {
                    Contact[] contacts = client.GetAllContacts();

                    foreach (Contact c in contacts)
                    {
                        if (c.EmailAddresses.Count > 0)
                            gmailContactsList.Add(new Components.GmailContact(c.DisplayName, c.EmailAddresses[0].Address));
                    }

                    GmailContactsGridView.DataSource = gmailContactsList;
                    GmailContactsGridView.DataBind();
                }
            }
        }

        #endregion Gmail To Umbraco

        #region Umbraco To Gmail

        public void UmbracoToGmailSyncResetControls()
        {
            ProcessSummaryDiv.Visible = UmbracoToGmail_MainDiv.Visible = NoRowSelectedErrorDiv.Visible = false;
            Into_Div.Visible = true;
        }

        protected void UmbracoToGmailSyncButton_Click(object sender, EventArgs e)
        {
            NoRowSelectedErrorDiv.Visible = false;

            if (ViewState["GmailDetails"] != null)
            {
                List<string> alreadyExistingList = new System.Collections.Generic.List<string>();
                
                if (UmbracoUsersGridView.Visible)
                {
                    List<IUser> selectedUsersList = new List<IUser>();

                    foreach (GridViewRow row in UmbracoUsersGridView.Rows)
                    {
                        if (row.RowType == DataControlRowType.DataRow)
                        {
                            CheckBox chkRow = (row.Cells[0].FindControl("SelectedCheckBox") as CheckBox);
                            if (chkRow.Checked)
                            {
                                string email = UmbracoUsersGridView.DataKeys[row.RowIndex].Value.ToString();
                                selectedUsersList.Add(ApplicationContext.Current.Services.UserService.GetByEmail(email));
                            }
                        }
                    }

                    if (selectedUsersList.Count > 0)
                    {
                        Aspose_GmailSync_ServerDetails serverDetails = (Aspose_GmailSync_ServerDetails)ViewState["GmailDetails"];

                        using (IGmailClient client = Aspose.Email.Google.GmailClient.GetInstance(serverDetails.ClientID, serverDetails.ClientSecret, serverDetails.RefreshToken))
                        {
                            Contact[] contacts = client.GetAllContacts();
                            Contact[] validContacts = (from contactsList in contacts where contactsList.EmailAddresses.Count > 0 select contactsList).ToArray<Contact>();

                            foreach (IUser user in selectedUsersList)
                            {
                                if (validContacts.FirstOrDefault(x => x.EmailAddresses[0].Address.Equals(user.Email)) == null)
                                {
                                    Contact contact = BuildNewGmailContact(user);
                                    client.CreateContact(contact, serverDetails.Email);
                                }
                                else
                                {
                                    alreadyExistingList.Add(user.Email);
                                }
                            }
                        }
                    }
                    else
                    {
                        NoRowSelectedErrorDiv.Visible = true;
                        return;
                    }

                    UmbracoToGmail_ImportedLiteral.Text = string.Format("{0} contact(s) have been imported to Gmail Server successfully.", (selectedUsersList.Count - alreadyExistingList.Count));

                }
                else
                {
                    List<IMember> selectedUsersList = new List<IMember>();

                    foreach (GridViewRow row in UmbracoMembersGridView.Rows)
                    {
                        if (row.RowType == DataControlRowType.DataRow)
                        {
                            CheckBox chkRow = (row.Cells[0].FindControl("SelectedCheckBox") as CheckBox);
                            if (chkRow.Checked)
                            {
                                string email = UmbracoMembersGridView.DataKeys[row.RowIndex].Value.ToString();
                                selectedUsersList.Add(ApplicationContext.Current.Services.MemberService.GetByEmail(email));
                            }
                        }
                    }

                    if (selectedUsersList.Count > 0)
                    {
                        Aspose_GmailSync_ServerDetails serverDetails = (Aspose_GmailSync_ServerDetails)ViewState["GmailDetails"];

                        using (IGmailClient client = Aspose.Email.Google.GmailClient.GetInstance(serverDetails.ClientID, serverDetails.ClientSecret, serverDetails.RefreshToken))
                        {
                            Contact[] contacts = client.GetAllContacts();
                            Contact[] validContacts = (from contactsList in contacts where contactsList.EmailAddresses.Count > 0 select contactsList).ToArray<Contact>();

                            foreach (IMember member in selectedUsersList)
                            {
                                if (validContacts.FirstOrDefault(x => x.EmailAddresses[0].Address.Equals(member.Email)) == null)
                                {
                                    Contact contact = BuildNewGmailContactFromMember(member);
                                    client.CreateContact(contact, serverDetails.Email);
                                }
                                else
                                {
                                    alreadyExistingList.Add(member.Email);
                                }
                            }
                        }
                    }
                    else
                    {
                        NoRowSelectedErrorDiv.Visible = true;
                        return;
                    }

                    UmbracoToGmail_ImportedLiteral.Text = string.Format("{0} contact(s) have been imported to Gmail Server successfully.", (selectedUsersList.Count - alreadyExistingList.Count));
                }
                
                if (alreadyExistingList.Count > 0)
                {
                    UmbracoToGmail_AlreadyExistingLiteral.Text = "The following contacts already exists in Gmail Server and therefore not imported";
                    foreach (string email in alreadyExistingList)
                        UmbracoToGmail_AlreadyExistingLiteral.Text += "<br>" + email;
                }

                UmbracoToGmail_ProcessSummaryDiv.Visible = true;
                Into_Div.Visible = false;
                UmbracoToGmail_MainDiv.Visible = false;
            }
        }

        private Contact BuildNewGmailContact(IUser user)
        {
            Contact contact = new Contact();
            EmailAddress ea = new EmailAddress();
            ea.Address = user.Email;
            contact.EmailAddresses.Work = ea;
            return contact;
        }

        private Contact BuildNewGmailContactFromMember(IMember user)
        {
            Contact contact = new Contact();
            EmailAddress ea = new EmailAddress();
            ea.Address = user.Email;
            contact.EmailAddresses.Work = ea;
            contact.DisplayName = user.Name;
            return contact;
        }

        protected void GetUmbracoUsersButton_Click(object sender, EventArgs e)
        {
            UmbracoMembersGridView.Visible = false;
            UmbracoUsersGridView.Visible = true;

            Into_Div.Visible = false;
            UmbracoToGmail_MainDiv.Visible = true;

            if (ViewState["GmailDetails"] != null)
            {
                var userService = ApplicationContext.Current.Services.UserService;
                int totalRecords = 0;
                UmbracoUsersGridView.DataSource = userService.GetAll(1, int.MaxValue, out totalRecords);
                UmbracoUsersGridView.DataBind();
            }
        }

        #endregion Umbraco To Gmail

        protected void GetUmbracoMembersButton_Click(object sender, EventArgs e)
        {
            UmbracoMembersGridView.Visible = true;
            UmbracoUsersGridView.Visible = false;

            Into_Div.Visible = false;
            UmbracoToGmail_MainDiv.Visible = true;

            if (ViewState["GmailDetails"] != null)
            {
                var memberService = ApplicationContext.Current.Services.MemberService;
                int totalRecords = 0;

                IEnumerable<IMember> listMembers = memberService.GetAll(1, int.MaxValue, out totalRecords);
                UmbracoMembersGridView.DataSource = listMembers;
                UmbracoMembersGridView.DataBind();
            }
        }
    }
}